home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / utilit~1 / initsnb.zoo / init / sh / input.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-09  |  8.9 KB  |  386 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Kenneth Almquist.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)input.c    5.4 (Berkeley) 7/1/91";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * This file implements the input routines used by the parser.
  43.  */
  44.  
  45. #include <stdio.h>    /* defines BUFSIZ */
  46. #include "shell.h"
  47. #include <fcntl.h>
  48. #include <errno.h>
  49. #include "syntax.h"
  50. #include "input.h"
  51. #include "output.h"
  52. #include "memalloc.h"
  53. #include "error.h"
  54.  
  55. #define EOF_NLEFT -99        /* value of parsenleft when EOF pushed back */
  56.  
  57.  
  58. /*
  59.  * The parsefile structure pointed to by the global variable parsefile
  60.  * contains information about the current file being read.
  61.  */
  62.  
  63. MKINIT
  64. struct parsefile {
  65.     int linno;        /* current line */
  66.     int fd;            /* file descriptor (or -1 if string) */
  67.     int nleft;        /* number of chars left in buffer */
  68.     char *nextc;        /* next char in buffer */
  69.     struct parsefile *prev;    /* preceding file on stack */
  70.     char *buf;        /* input buffer */
  71. };
  72.  
  73.  
  74. int plinno = 1;            /* input line number */
  75. MKINIT int parsenleft;        /* copy of parsefile->nleft */
  76. char *parsenextc;        /* copy of parsefile->nextc */
  77. MKINIT struct parsefile basepf;    /* top level input file */
  78. char basebuf[BUFSIZ];        /* buffer for top level input file */
  79. struct parsefile *parsefile = &basepf;    /* current input file */
  80. char *pushedstring;        /* copy of parsenextc when text pushed back */
  81. int pushednleft;        /* copy of parsenleft when text pushed back */
  82.  
  83. #ifdef __STDC__
  84. STATIC void pushfile(void);
  85. #else
  86. STATIC void pushfile();
  87. #endif
  88.  
  89.  
  90.  
  91. #ifdef mkinit
  92. INCLUDE "input.h"
  93. INCLUDE "error.h"
  94.  
  95. INIT {
  96.     extern char basebuf[];
  97.  
  98.     basepf.nextc = basepf.buf = basebuf;
  99. }
  100.  
  101. RESET {
  102.     if (exception != EXSHELLPROC)
  103.         parsenleft = 0;            /* clear input buffer */
  104.     popallfiles();
  105. }
  106.  
  107. SHELLPROC {
  108.     popallfiles();
  109. }
  110. #endif
  111.  
  112.  
  113. /*
  114.  * Read a line from the script.
  115.  */
  116.  
  117. char *
  118. pfgets(line, len)
  119.     char *line;
  120.     {
  121.     register char *p = line;
  122.     int nleft = len;
  123.     int c;
  124.  
  125.     while (--nleft > 0) {
  126.         c = pgetc_macro();
  127.         if (c == PEOF) {
  128.             if (p == line)
  129.                 return NULL;
  130.             break;
  131.         }
  132.         *p++ = c;
  133.         if (c == '\n')
  134.             break;
  135.     }
  136.     *p = '\0';
  137.     return line;
  138. }
  139.  
  140.  
  141.  
  142. /*
  143.  * Read a character from the script, returning PEOF on end of file.
  144.  * Nul characters in the input are silently discarded.
  145.  */
  146.  
  147. int
  148. pgetc() {
  149.     return pgetc_macro();
  150. }
  151.  
  152.  
  153. /*
  154.  * Refill the input buffer and return the next input character:
  155.  *
  156.  * 1) If a string was pushed back on the input, switch back to the regular
  157.  *    buffer.
  158.  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
  159.  *    from a string so we can't refill the buffer, return EOF.
  160.  * 3) Call read to read in the characters.
  161.  * 4) Delete all nul characters from the buffer.
  162.  * 5) Delete all \015 characters from the buffer (neuhaus@informatik.uni-kl.de,
  163.  *    1 May, 1992
  164.  */
  165.  
  166. int
  167. preadbuffer() {
  168.     register char *p, *q;
  169.     register int i;
  170.  
  171.     if (pushedstring) {
  172.         parsenextc = pushedstring;
  173.         pushedstring = NULL;
  174.         parsenleft = pushednleft;
  175.         if (--parsenleft >= 0)
  176.             return *parsenextc++;
  177.     }
  178.     if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
  179.         return PEOF;
  180.     flushout(&output);
  181.     flushout(&errout);
  182. retry:
  183.     p = parsenextc = parsefile->buf;
  184.     i = read(parsefile->fd, p, BUFSIZ);
  185.     if (i <= 0) {
  186.                 if (i < 0) {
  187.                         if (errno == EINTR)
  188.                                 goto retry;
  189. #ifndef __MINT__
  190.                         if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
  191.                                 int flags = fcntl(0, F_GETFL, 0);
  192.                                 if (flags >= 0 && flags & O_NONBLOCK) {
  193.                                         flags &=~ O_NONBLOCK;
  194.                                         if (fcntl(0, F_SETFL, flags) >= 0) {
  195.                         out2str("sh: turning off NDELAY mode\n");
  196.                                                 goto retry;
  197.                                         }
  198.                                 }
  199.                         }
  200. #endif
  201.                 }
  202.                 parsenleft = EOF_NLEFT;
  203.                 return PEOF;
  204.     }
  205.     parsenleft = i - 1;
  206.  
  207.     /* delete nul characters (and \015 (CR), neuhaus 1 May, 1992) */
  208.     for (;;) {
  209.         if (*p++ == '\0' || *(p-1) == '\015')
  210.             break;
  211.         if (--i <= 0)
  212.             return *parsenextc++;        /* no nul characters */
  213.     }
  214.     q = p - 1;
  215.     while (--i > 0) {
  216.         if (*p != '\0' && *p != '\015')
  217.             *q++ = *p;
  218.         p++;
  219.     }
  220.     if (q == parsefile->buf)
  221.         goto retry;            /* buffer contained nothing but nuls */
  222.     parsenleft = q - parsefile->buf - 1;
  223.     return *parsenextc++;
  224. }
  225.  
  226.  
  227. /*
  228.  * Undo the last call to pgetc.  Only one character may be pushed back.
  229.  * PEOF may be pushed back.
  230.  */
  231.  
  232. void
  233. pungetc() {
  234.     parsenleft++;
  235.     parsenextc--;
  236. }
  237.  
  238.  
  239. /*
  240.  * Push a string back onto the input.  This code doesn't work if the user
  241.  * tries to push back more than one string at once.
  242.  */
  243.  
  244. void
  245. ppushback(string, length)
  246.     char *string;
  247.     {
  248.     pushedstring = parsenextc;
  249.     pushednleft = parsenleft;
  250.     parsenextc = string;
  251.     parsenleft = length;
  252. }
  253.  
  254.  
  255.  
  256. /*
  257.  * Set the input to take input from a file.  If push is set, push the
  258.  * old input onto the stack first.
  259.  */
  260.  
  261. void
  262. setinputfile(fname, push)
  263.     char *fname;
  264.     {
  265.     int fd;
  266.     int fd2;
  267.  
  268.     INTOFF;
  269.     if ((fd = open(fname, O_RDONLY)) < 0)
  270.         error("Can't open %s", fname);
  271.     if (fd < 10) {
  272.         fd2 = copyfd(fd, 10);
  273.         close(fd);
  274.         if (fd2 < 0)
  275.             error("Out of file descriptors");
  276.         fd = fd2;
  277.     }
  278.     setinputfd(fd, push);
  279.     INTON;
  280. }
  281.  
  282.  
  283. /*
  284.  * Like setinputfile, but takes an open file descriptor.  Call this with
  285.  * interrupts off.
  286.  */
  287.  
  288. void
  289. setinputfd(fd, push) {
  290.     if (push) {
  291.         pushfile();
  292.         parsefile->buf = ckmalloc(BUFSIZ);
  293.     }
  294.     if (parsefile->fd > 0)
  295.         close(parsefile->fd);
  296.     parsefile->fd = fd;
  297.     if (parsefile->buf == NULL)
  298.         parsefile->buf = ckmalloc(BUFSIZ);
  299.     parsenleft = 0;
  300.     plinno = 1;
  301. }
  302.  
  303.  
  304. /*
  305.  * Like setinputfile, but takes input from a string.
  306.  */
  307.  
  308. void
  309. setinputstring(string, push)
  310.     char *string;
  311.     {
  312.     INTOFF;
  313.     if (push)
  314.         pushfile();
  315.     parsenextc = string;
  316.     parsenleft = strlen(string);
  317.     parsefile->buf = NULL;
  318.     plinno = 1;
  319.     INTON;
  320. }
  321.  
  322.  
  323.  
  324. /*
  325.  * To handle the "." command, a stack of input files is used.  Pushfile
  326.  * adds a new entry to the stack and popfile restores the previous level.
  327.  */
  328.  
  329. STATIC void
  330. pushfile() {
  331.     struct parsefile *pf;
  332.  
  333.     parsefile->nleft = parsenleft;
  334.     parsefile->nextc = parsenextc;
  335.     parsefile->linno = plinno;
  336.     pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
  337.     pf->prev = parsefile;
  338.     pf->fd = -1;
  339.     parsefile = pf;
  340. }
  341.  
  342.  
  343. void
  344. popfile() {
  345.     struct parsefile *pf = parsefile;
  346.  
  347.     INTOFF;
  348.     if (pf->fd >= 0)
  349.         close(pf->fd);
  350.     if (pf->buf)
  351.         ckfree(pf->buf);
  352.     parsefile = pf->prev;
  353.     ckfree(pf);
  354.     parsenleft = parsefile->nleft;
  355.     parsenextc = parsefile->nextc;
  356.     plinno = parsefile->linno;
  357.     INTON;
  358. }
  359.  
  360.  
  361. /*
  362.  * Return to top level.
  363.  */
  364.  
  365. void
  366. popallfiles() {
  367.     while (parsefile != &basepf)
  368.         popfile();
  369. }
  370.  
  371.  
  372.  
  373. /*
  374.  * Close the file(s) that the shell is reading commands from.  Called
  375.  * after a fork is done.
  376.  */
  377.  
  378. void
  379. closescript() {
  380.     popallfiles();
  381.     if (parsefile->fd > 0) {
  382.         close(parsefile->fd);
  383.         parsefile->fd = 0;
  384.     }
  385. }
  386.